package view;

import java.awt.*;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.*;

import chess.GroupsHelper;
import chess.RadioGroup;


/**
 * This class in a setupMenu that greets the user upon creation of a new game.  
 * It includes items for gametype as well as visual elements.
 * @author Ben
 */
@SuppressWarnings("serial")
public class SetupMenu extends JFrame
{
	
	/**
	 * This {@link java.awt.event.ActionListener} is the listener used to receive events fired by the {@link view.SetupMenu}.
	 * It is also the controller, although it is encapsulated with the class cast.
	 */
	private ActionListener listener;
	
	/**
	 * This {@link javax.swing.JPanel} contains all the elements on the left side of the {@link view.SetupMenu}'s frame.
	 * It holds all the different radio buttons necessary to select items.
	 */
	private JPanel selections;
	
	/**
	 * This {@link javax.swing.JPanel} contains all the elements on the right side of the {@link view.SetupMenu}'s frame.
	 * It holds all the different graphics that are thrown when a radio button is selected.
	 */
	private JPanel displays;
	
	/**
	 * This {@link view.MessageField} is near the bottom of the frame and holds the name of the game to be created.
	 */
	private MessageField gameName;
	
	/**
	 * This String array holds all the settings that are selected while the SetupMenu is being used.  
	 * When the SetupMenu is closed, these settings are sent to the controller as the final selections from the user for the upcoming game.
	 */
	String[] allSettings;
	
	/**
	 * This boolean represents whether this instance of SetupMenu is occuring before the game or not.  
	 * SetupMenus before and during the game have different requirements and display different items.
	 */
	boolean beforeGame;
	
	/**
	 * This constructor creates a new {@link view.SetupMenu} 
	 * @param listener - The listener for this view element
	 * @param beforeGame - boolean that determines whether this SetupMenu is being built during the game or before it.
	 */
	public SetupMenu(ActionListener listener, boolean beforeGame)
	{
		this.beforeGame = beforeGame;
		allSettings = new String[] {"1", "104", "100", "201", "300", ""};
		
		this.listener = listener;
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		if(beforeGame)
		{
			this.setTitle("Settings");
			this.setSize(360,630);
		}
		else
		{
			this.setTitle("Skin Settings");
			this.setSize(320,470);
		}

		this.setResizable(false);
		this.setLayout(new GridBagLayout());
		
		GridBagConstraints constraints = new GridBagConstraints(0, GridBagConstraints.RELATIVE, GridBagConstraints.REMAINDER, 1, .4, .4, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2,2,2,2), 2, 2);
		JPanel selections = setupRadios(constraints);
		JPanel displays = setupDisplays(constraints);
		JPanel exit = setupExit();

		GridBagConstraints topLayerConstraints = new GridBagConstraints(0, 0, GridBagConstraints.RELATIVE, 1, .8, .8, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2,2,2,2), 2, 2);
		
		this.add(selections, topLayerConstraints);
		topLayerConstraints.gridx = GridBagConstraints.RELATIVE;
		topLayerConstraints.gridwidth = GridBagConstraints.REMAINDER;
		
		this.add(displays, topLayerConstraints);
		topLayerConstraints.gridx = 0;
		topLayerConstraints.gridy = GridBagConstraints.RELATIVE;
		
		if(beforeGame)
		{
			topLayerConstraints.gridheight = 20;
			
			this.add(new JLabel("Enter game name:"), topLayerConstraints);
			topLayerConstraints.gridheight = GridBagConstraints.RELATIVE;
		
			gameName = new MessageField();
			this.add(gameName, topLayerConstraints);
		}
		
		topLayerConstraints.gridheight = GridBagConstraints.REMAINDER;
		this.add(exit, topLayerConstraints);
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		int xPos = (screen.width / 2) - (this.getWidth() / 2); // Center horizontally.
		int yPos = (screen.height / 2) - (this.getHeight() / 2); // Center vertically.
		this.setLocation(xPos, yPos);
		this.invalidate();
		this.validate();
		this.repaint();
		this.setVisible(true);
	}
	
	/**
	 * This method sets up the left hand side JPanel for the SetupMenu
	 * It contains all the radio groups and items that can be selected.
	 * All the radio button information, including labels and ActionCommands 
	 * are actually stored and read in from a text file using {@link chess.GroupsHelper}.
	 * @param constraints - the GridBagConstraint used for the JPanel
	 * @return - the newly created and formatted JPanel for use in the JFrame
	 */
	private JPanel setupRadios(GridBagConstraints constraints)
	{
		selections = new JPanel(new GridBagLayout());
		ArrayList<String>[][] allSelectionInfo = GroupsHelper.importData("config/Main Radio Groups.cfg");
		int numItemsSel = allSelectionInfo[0].length;
		
		if(beforeGame)
		{
			RadioGroup[] radioList = new RadioGroup[numItemsSel];
			for(int x = 0; x < numItemsSel; x++)
			{
				radioList[x] = new RadioGroup(listener, allSelectionInfo[1][x], allSelectionInfo[2][x], true);
				selections.add(new JLabel(allSelectionInfo[0][x].get(0)), constraints);
				selections.add(radioList[x], constraints);
			}
		}
		else
		{
			RadioGroup[] radioList = new RadioGroup[numItemsSel-1];
			for(int x = 1; x < numItemsSel; x++)
			{
				radioList[x-1] = new RadioGroup(listener, allSelectionInfo[1][x], allSelectionInfo[2][x], false);
				//radioList[x-1].getRadioButtons().get(0).setSelected(false);
				selections.add(new JLabel(allSelectionInfo[0][x].get(0)), constraints);
				selections.add(radioList[x-1], constraints);
			}			
		}
			
		return selections;
	}
	
	/**
	 * This method sets up the right hand side JPanel for the SetupMenu
	 * It contains all the displays that can be updated and viewed.
	 * All the dispay information, including pictures
	 * are actually stored and read in from a text file using {@link chess.GroupsHelper}.
	 * @param constraints - the GridBagConstraint used for the JPanel
	 * @return - the newly created and formatted JPanel for use in the JFrame
	 */
	private JPanel setupDisplays(GridBagConstraints constraints)
	{
		displays = new JPanel(new GridBagLayout());
		ArrayList<String>[][] allDisplayInfo = GroupsHelper.importData("config/Picture Groups.cfg");

		int numItemsDisp = allDisplayInfo[0].length;
		for(int x = 0; x < numItemsDisp; x++)
		{
			if(!beforeGame && x==0)
				constraints.weighty = .1;
			else
				constraints.weighty = Double.parseDouble(allDisplayInfo[1][x].get(0));

			JPanel backgroundContainer = new JPanel();
			for(int y = 0; y < allDisplayInfo[0][x].size(); y++)
				backgroundContainer.add(new JLabel(new ImageIcon(allDisplayInfo[0][x].get(y))));
			displays.add(backgroundContainer, constraints);

			constraints.weighty = Double.parseDouble((allDisplayInfo[1][x].get(1)));
		}
		return displays;
	}

	/**
	 * This method creates a formatted JPanel that contains a 
	 * JButton used for exiting the SetupMenu
	 * @return - the newly created and formatted JPanel for use in the JFrame
	 */
	private JPanel setupExit()
	{
		JButton exitLabel = new JButton("Save and Exit");
		exitLabel.setHorizontalAlignment(SwingConstants.CENTER);
		exitLabel.addActionListener(listener);
		
		if(beforeGame)
			exitLabel.setActionCommand("exit initial setup");
		else
			exitLabel.setActionCommand("exit skin setup");
			
		
		JPanel exit = new JPanel();
		exit.add(exitLabel);
		return exit;
	}

	/**
	 * This method changes a display element on the right side of the SetupMenu
	 * @param item - the item to be changed
	 * @param command - the Integer command that changes the display
	 */
	public void changeDisplay(int item, int command)
	{
		try
		{
			JPanel modify = new JPanel();
			modify = (JPanel) displays.getComponent(item);
			modify.removeAll();
			modify.repaint();
			
			if(command == 1)
				return;
			else if(command == 2)
				modify.add(new RadioGroup(listener, new ArrayList<String>() {{add("Dumb AI"); add("Smart AI");}}, new ArrayList<String>() {{add("05"); add("06");}}, false));
			else if(command == 3)
				modify.add(new RadioGroup(listener, new ArrayList<String>() {{add("Dumb AI"); add("Smart AI");}}, new ArrayList<String>() {{add("07"); add("08");}}, false));
			else if(command < 200)
				modify.add(new JLabel(new ImageIcon(ImageIO.read(new File("skins/" + command + "/King.png")))));
			else if(command < 300)
			{
				modify.add(new JLabel(new ImageIcon(ImageIO.read(new File("skins/" + command + "/White.jpg")))));
				modify.add(new JLabel(new ImageIcon(ImageIO.read(new File("skins/" + command + "/Black.jpg")))));
			}
			else
				modify.add(new JLabel(new ImageIcon(ImageIO.read(new File("skins/" + command + "/Highlight.jpg")))));

			modify.invalidate();
			modify.validate();
			modify.repaint();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * This method records the game name typed into the Message Area into allSettings.
	 */
	public void recordGameName()
	{
		try
		{
			allSettings[5] = gameName.getText() + ".sav";
		}
		catch(NullPointerException e)
		{
			allSettings[5] = "";
		}
	}
	
	public void recordSetting(int item, int command) 
	{
		allSettings[item] = ((Integer)command).toString();
	}

	public String[] getAllSettings() 
	{
		recordGameName();
		return allSettings;
	}
}
